package com.kdgc.energy.dmm;


import com.kdgc.energy.dmm.entity.EntityClassReader;
import com.kdgc.energy.dmm.lambda.Lambda;
import com.kdgc.energy.dmm.lambda.LambdaUtil;
import com.kdgc.energy.dmm.lambda.SerializedFunction;
import com.kdgc.energy.dmm.table.Table;
import com.kdgc.energy.dmm.util.NameUtil;
import org.apache.metamodel.schema.MutableColumn;

import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 运行时环境
 *
 * @author xu.wenchang
 * @version 1.0 2022/04/14
 */
public final class Environment {
    private static final Map<String, Table> TABLE_MAP;
    private static volatile DataSource dataSource;
    /**
     * 是否开启执行时间统计
     */
    private static volatile boolean openExecuteTimeStatistics;
    
    /**
     * 是否显示SQL
     */
    private static volatile boolean showSQL;
    
    /**
     * writer
     */
    private static volatile InfoWriter writer;
    
    static {
        TABLE_MAP = new ConcurrentHashMap<>();
    }
    
    public static Table findByTableName(String tableName) {
        return TABLE_MAP.values()
                        .stream()
                        .filter(table -> table.getEntityInfo()
                                              .getTableName()
                                              .equals(tableName))
                        .findFirst()
                        .orElse(null);
    }
    
    
    public static <T, R> String getColumnName(SerializedFunction<? extends T, ? extends R> f) {
        try {
            return NameUtil.getColumnName(get(f));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    public static <T, R> MutableColumn get(SerializedFunction<? extends T, ? extends R> f) {
        try {
            Lambda lambda = LambdaUtil.toLambda(f.getClass(), f);
            Table table = TABLE_MAP.computeIfAbsent(lambda.getClassName(), key -> new Table(new EntityClassReader(lambda.getClazz()).read()));
            return table.getColumn(lambda.getMethodName());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    public static Table get(final Class<?> clazz) {
        String className = clazz.getCanonicalName()
                                .replaceAll("\\.", "/");
        return TABLE_MAP.computeIfAbsent(className, key -> new Table(new EntityClassReader(clazz).read()));
    }
    
    public static String getTableName(final Class<?> clazz) {
        return NameUtil.getTableName(get(clazz).getTable());
    }
    
    /**
     * 开启执行时间统计
     */
    public static synchronized void openExecuteTimeStatistics() {
        openExecuteTimeStatistics = true;
    }
    
    /**
     * 关闭执行时间统计
     */
    public static synchronized void closeExecuteTimeStatistics() {
        openExecuteTimeStatistics = false;
    }
    
    /**
     * 显示执行SQL
     */
    public static synchronized void showSQL() {
        showSQL = true;
    }
    
    /**
     * 隐藏执行SQL
     */
    public static synchronized void hideSQL() {
        showSQL = false;
    }
    
    public static synchronized void setInfoWriter(InfoWriter infoWriter) {
        writer = infoWriter;
    }
    
    public static boolean isShowSQL() {
        return showSQL;
    }
    
    public static boolean isStatExecTime() {
        return openExecuteTimeStatistics;
    }
    
    public static InfoWriter getWriter() {
        return writer;
    }
    
    public static void setWriter(InfoWriter infoWriter) {
        writer = infoWriter;
    }
    
    public static synchronized void setDataSource(DataSource ds) {
        dataSource = ds;
    }
    
    public static DataSource getDataSource() {
        return dataSource;
    }
}
